#ifndef SYSYF_COMSUBEXPRELI_H
#define SYSYF_COMSUBEXPRELI_H

#include "Pass.h"
#include <map>
#include <set>
#include "Instruction.h"
struct cmp_inst //定义指令的比较，用于实现集合set的操作
{
    bool operator()(Instruction *a, Instruction *b) const
    {
        if (a->get_instr_op_name() != b->get_instr_op_name())
        {
            return (a->get_instr_op_name() < b->get_instr_op_name());
        }
        else
        {
            auto is_a_cmp = dynamic_cast<CmpInst *>(a);
            auto is_b_cmp = dynamic_cast<CmpInst *>(b);
            if (is_a_cmp && is_b_cmp)
            {
                return (is_a_cmp->get_cmp_op() < is_b_cmp->get_cmp_op());
            }
        }
        if (a->get_operands().size() < b->get_operands().size())
        {
            return true;
        }
        else if (a->get_operands().size() > b->get_operands().size())
        {
            return false;
        }
        for (auto a_iter = a->get_operands().begin(), b_iter = b->get_operands().begin(); a_iter != a->get_operands().end(); a_iter++, b_iter++)
        {
            if (*a_iter != *b_iter)
            {
                auto const_a_opr = dynamic_cast<ConstantInt *>(*a_iter);
                auto const_b_opr = dynamic_cast<ConstantInt *>(*b_iter);
                if (const_a_opr && const_b_opr)
                {
                    if (const_a_opr->get_value() != const_b_opr->get_value())
                    {
                        return (const_a_opr->get_value() < const_b_opr->get_value());
                    }
                }
                else
                {
                    return ((*a_iter)->get_name() < (*b_iter)->get_name());
                }
            }
        }
        return false;
    }
};

/*****************************CommonSubExprElimination**************************************/
/***************************This class is based on SSA form*********************************/
/***************************you need to finish this class***********************************/
class ComSubExprEli : public Pass
{
public:
    explicit ComSubExprEli(Module *module) : Pass(module) {}
    const std::string get_name() const override { return name; }
    void execute() override;
    static bool is_valid_expr(Instruction *inst);
    void available_expr_analysis(Function *fun); //计算每个基本块的in和out
    void global_common_expr_delete(Function *fun);
    void compute_gen(Function *fun);

private:
    const std::string name = "ComSubExprEli";
};

#endif // SYSYF_COMSUBEXPRELI_H